package json;

import bean.Book;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JavaJson {

    public static void main(String[] args) {
        Book lmy = new Book(100, "lmy");
        //创建一个Gson对象，作为工具
        Gson gson = new Gson();

        //1.javaBean -> Json字符串
        String stringBook = gson.toJson(lmy);
        System.out.println(stringBook);

        //2.Json字符串 -> javaBean
        /*
            stringBook 是满足json格式的json字符串
            Book.class 指定将json字符串转换成Book类型
            底层是反射机制
         */
        Book book = gson.fromJson(stringBook, Book.class);
        System.out.println(book);

        //3.list对象 -> json字符串
        List<Book> books = new ArrayList<>();
        books.add(book);
        books.add(new Book(200, "lmy2"));
        String stringBookList = gson.toJson(books);
        System.out.println(stringBookList);

        //4.json字符串 -> list对象
        /*
            I)如果需要把json字符串转成集合这种复杂的类型，需要使用Gson提供的类 TypeToken
            II)TypeToken 是一个自定义泛型类
            III)gson的设计者，需要先得到类的完整路径，然后在底层进行反射
            IV)因为TypeToken的无参构造器是protected，而 new TypeToken<List<Book>>() 是调用其无参构造器，
               但protected的使用范围是要在同一包下，所以无法使用构造器
            V)而new TypeToken<List<Book>>() {} 就可以使用，它是一个匿名内部类，它有自己的无参构造器(隐式)
            VI)这个匿名内部类可以堪称TypeToken的子类，当创建匿名内部类时执行其无参构造器，会默认先调用父类无参构造器super()
            VII)相当于是用匿名内部类做跳板来执行到TypeToken的无参构造器
         */
        //type = java.util.List<bean.Book> 是要反射的全路径
        Type type = new TypeToken<List<Book>>() {}.getType();
        System.out.println("type = " + type);
        System.out.println(type.getClass());
        List<Book> list = gson.fromJson(stringBookList, type);
        System.out.println(list);

        //5.map对象 -> json字符串
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("name", "lmy");
        hashMap.put("author", "lmy2");
        String stringBookMap = gson.toJson(hashMap);
        System.out.println(stringBookMap);

        //6.json字符串 -> map对象
        // new TypeToken<Map<String, Object>>() {
        //        }.getType()  -> java.util.Map<java.lang.String,bean.Book>
        Map<String, Object> map = gson.fromJson(stringBookMap, new TypeToken<Map<String, Object>>() {
        }.getType());
        System.out.println(map);
    }
}
